<template>
  <div ref="chatBox" class="chat-container">
    <chat-messages v-model:is-loading="isLoading" :messages="messages" @suggestion-click="handleSuggestionClick" />
    <!--          @preview-file="previewFile"-->
    <input-area
      v-model:message="yourMessage"
      v-model:input-type="inputType"
      v-model:select-input-type-value="selectInputTypeValue"
      v-model:files="uploadedFiles"
      v-model:is-loading="isLoading"
      v-model:inputs="inputs"
      :curren-task-id="currenTaskId"
      :current-user="currentUser"
      @send-message="sendMessage"
      @upload="handleUpload"
      @remove-file="removeFile"
      @stop-message="isLoading = false"
      @handle-upload-confirm="handleUploadConfirm"
    />
    <upload-dialog
      ref="uploadDialog"
      v-model:visible="uploadVisible"
      :user="currentUser"
      @confirm="handleUploadConfirm"
    />

    <!--    <t-back-top-->
    <!--      container=".chat-container"-->
    <!--      :visible-height="0"-->
    <!--      style="position: absolute"-->
    <!--      :offset="['24px', '80px']"-->
    <!--      class="custom-back-bottom"-->
    <!--      :icon="ChevronDownIcon"-->
    <!--      @click="scrollToBottom"-->
    <!--    />-->
  </div>
</template>

<script lang="ts">
export default {
  name: 'ChatBase',
};
</script>

<script setup lang="ts">
import { ref, reactive, onMounted, watch, onBeforeUnmount } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { MessagePlugin } from 'tdesign-vue-next';
// import { ChevronDownIcon } from 'tdesign-icons-vue-next';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/store';
import { fetchMessages, postMessageAPI } from '@/api/coze';
import ChatMessages from './components/ChatMessage.vue';
import InputArea from '../chat/components/InputArea.vue';
import UploadDialog from '../chat/components/UploadDialog.vue';
import { getFileType } from './constants';
import icon1 from '@/assets/input-type-scheduling.png';
import icon2 from '@/assets/input-type-fault.png';
import icon3 from '@/assets/input-type-dailyMalfunctions.png';
import icon4 from '@/assets/input-type-check.png';
import icon5 from '@/assets/mall_coupon_healthcard.png';
import icon6 from '@/assets/knowledge-retrieval.png';

const route = useRoute();
const router = useRouter();
const user = useUserStore();

// 数据定义
const messages = reactive([]);
const yourMessage = ref('');
const isLoading = ref(false);
const uploadedFiles = ref([]);
const uploadVisible = ref(false);
const currentUser = ref(''); // 用户名
const currentConversationId = ref(null); // 用于跟踪会话ID
const currenTaskId = ref('');
const chatBox = ref(null); // 获取滚动容器引用
// 响应式自动滚动标志
const autoScroll = ref(true);
// 滚动阈值（距离底部 50px 视为在底部区域）
const SCROLL_THRESHOLD = 100;
const inputs = ref({}); // 接口请求体 参数
const selectInputTypeValue = ref(-1);

const inputType = ref([
  { name: '知识检索', img: icon6 },
  { name: '排班助手', img: icon1 },
  { name: '干线故障统计', img: icon2 },
  { name: '日常故障统计', img: icon3 },
  { name: '党建会议记录核查', img: icon4 },
  { name: '传输1+N报表', img: icon5 },
]);

// 方法定义（sendMessage、handleUpload 等保持不变）
// 消息发送逻辑
const sendMessage = useDebounceFn(async () => {
  if (!yourMessage.value.trim() || isLoading.value) return;

  const userMessage = {
    inputs: inputs.value,
    query: yourMessage.value.trim(), // 消息作为用户输入
    response_mode: 'streaming', // 强制使用流式
    user: currentUser.value, // 用户ID
    conversation_id: currentConversationId.value || '', // 如果需要连续对话则传入
    files: [], // 如果上传文件需补充
    auto_generate_name: true, // 可选：自动生成标题
  };
  // 判断是否存在 上传文件
  if (uploadedFiles.value && uploadedFiles.value.length > 0) {
    userMessage.files = uploadedFiles.value.map((file) => ({
      type: getFileType(file.response.extension), // 使用映射函数
      transfer_method: 'local_file',
      upload_file_id: file.response.id, // 假设已上传并获取ID
    }));
  }
  // 是否应用了场景
  // if (typeof selectInputTypeValue.value === 'number' && inputType.value[selectInputTypeValue.value]?.name) {
  //   userMessage.inputs.scene = inputType.value[selectInputTypeValue.value]?.name;
  // }
  console.log('userMessage', userMessage);
  try {
    isLoading.value = true;

    // 生成临时消息ID
    const tempMessageId = `assistant_${Date.now()}`;
    // 立即显示用户消息
    messages.push({
      id: `user_${Date.now()}`,
      type: 'user',
      content: yourMessage.value.trim(),
      timestamp: Date.now(),
    });
    console.log('messages', messages);
    scrollToBottom();
    // 预添加加载中的助手消息
    const assistantMsg = {
      id: tempMessageId,
      message_id: null, // 占位用于后续更新
      type: 'assistant', // 判断类型 区分 助手回答内容与用户发送内容
      content: '', // 主内容
      isLoading: true, // 主内容加载状态标识
      isTemp: true, // 临时标记
      timestamp: Date.now(), // 发送时间戳
      isThinkingLoading: false, // 深度思考初始加载状态
      showThinking: false, // 是否展开深度思考面板
      thinkingContent: '', // 思考内容存储
    };
    messages.push(assistantMsg);
    scrollToBottom();

    yourMessage.value = ''; // 清除输入框内容
    const reader = await postMessageAPI(userMessage);
    await handleStream(reader, tempMessageId);
  } catch (error) {
    const idx = messages.findIndex((m) => m.isTemp);
    if (idx > -1) {
      messages[idx].content = `请求失败: ${error.message}`;
      messages[idx].isLoading = false;
      messages[idx].is = false;
      messages[idx].isTemp = false;
    }
    handleError(error);
  } finally {
    isLoading.value = false;
    scrollToBottom();
  }
}, 300);

// 处理流式响应
const handleStream = async (response, tempId) => {
  const decoder = new TextDecoder();
  let buffer = '';
  let finalMessageId = '';
  let hasReceivedFirstChunk = false; // 单纯时序标记
  let hasReceivedValidContent = false; // 有效内容标记

  try {
    while (true) {
      // eslint-disable-next-line no-await-in-loop
      const { done, value } = await response.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });
      // console.log('buffer', buffer);
      // 更健壮的分块处理
      while (buffer.includes('\n\n')) {
        const chunkEnd = buffer.indexOf('\n\n');
        const chunk = buffer.slice(0, chunkEnd);
        buffer = buffer.slice(chunkEnd + 2);

        if (!chunk.startsWith('data:')) continue;
        try {
          const jsonStr = chunk.replace('data:', '').trim();
          const { event, ...data } = JSON.parse(jsonStr);
          // console.log('event:', event, 'data:', data);

          // 有效内容标记更新
          if (data.answer?.trim()) {
            hasReceivedValidContent = true;
          }

          // 记录第一个有效message_id
          if (data.message_id && !finalMessageId && hasReceivedValidContent) {
            finalMessageId = data.message_id;
            // 关联临时消息
            const tempMsg = messages.find((m) => m.id === tempId);
            if (tempMsg) {
              tempMsg.message_id = finalMessageId;
              tempMsg.isTemp = false;
              tempMsg.isLoading = !hasReceivedFirstChunk;
            }
          }
          // console.log('handleStreamEvent _isFirstChunk', !hasReceivedFirstChunk);
          handleStreamEvent(event, {
            ...data,
            // 注入关联信息
            _tempId: tempId,
            _isFirstChunk: !hasReceivedFirstChunk,
          });
          // console.log('handleStreamEvent hasReceivedFirstChunk = true');
          if (!hasReceivedFirstChunk) hasReceivedFirstChunk = true;
        } catch (e) {
          console.error('Parse error', e);
        }
      }
    }
  } catch (error) {
    console.error('[SSE] 流处理异常:', error);
    // 更新临时消息状态
    const tempMsg = messages.find((m) => m.id === tempId);
    if (tempMsg) {
      tempMsg.content = '流传输中断，请重试';
      tempMsg.isLoading = false;
      tempMsg.isTemp = false;
    }
  }
};

// 处理不同消息类型
const handleStreamEvent = (event, data) => {
  // eslint-disable-next-line default-case
  switch (event) {
    case 'workflow_started':
      currenTaskId.value = data?.task_id; // 存储taskID 用于终止响应
      // TODO 修改路由逻辑需要修改 不然每次发起会话内容 都会重置url
      currentConversationId.value = data?.conversation_id; // conversation_id 用于修改路由地址
      // 更新 URL 的查询参数
      router.replace({
        path: `${currentConversationId.value}`,
        query: {
          ...route.query, // 保留现有的查询参数
          type: undefined, // 可选：移除 type 参数，避免重复触发逻辑
        },
      });
      break;
    // 文本块事件 case agent_message 是机器人流式数据; case message 是大模型流式数据
    // case 'agent_message'
    case 'message':
      handleMessageDelta(data);
      break;

    // 文件事件
    case 'message_file':
      messages.push({
        type: 'file',
        content: data.url,
        fileType: data.type,
      });
      break;

    // 消息结束
    case 'parallel_branch_finished':
      // 分支完成计数器
      branchStatus.pendingBranches = Math.max(0, branchStatus.pendingBranches - 1);

      // 启动安全计时器（根据业务设置合理时间，示例设为10秒）
      branchStatus.timeoutId = setTimeout(() => {
        if (branchStatus.pendingBranches === 0) {
          forceFinalize(data);
        }
      }, 10000);

      // 更新最后活动时间
      branchStatus.lastActivity = Date.now();
      break;

    case 'message_end':
      // 清除可能存在的超时
      clearTimeout(branchStatus.timeoutId);
      // 正常处理流程
      finalizeMessage(data);
      break;
    // 错误事件
    case 'error':
      handleError(data);
      break;

    // TTS音频等其他事件
    case 'tts_message':
      // 处理音频...
      break;
    case 'done':
      // 清理工作
      console.log('done');
      break;
  }
};

// 处理分块消息
const handleMessageDelta = (data: {
  // eslint-disable-next-line camelcase
  message_id: any;
  _tempId: any;
  answer: any;
  _isFirstChunk: any;
  // eslint-disable-next-line camelcase
  conversation_id: any;
}) => {
  let existingMsg = data.message_id ? messages.find((m) => m.message_id === data.message_id) : null;

  // 次之通过临时ID查找
  // eslint-disable-next-line no-underscore-dangle
  if (!existingMsg && data._tempId) {
    // eslint-disable-next-line no-underscore-dangle
    existingMsg = messages.find((m) => m.id === data._tempId);
  }
  if (existingMsg) {
    // 提取 思考内容 和 正文内容
    const { cleanedContent, thinkingContent } = extractThinkingContent(data.answer);
    // 增量更新思考内容
    if (thinkingContent) {
      existingMsg.thinkingContent = (existingMsg.thinkingContent || '') + thinkingContent;
      existingMsg.showThinking = true; // 控制折叠面板展开
      existingMsg.isThinkingLoading = true;
    }

    // 更新主内容
    existingMsg.content += cleanedContent;

    // 首次收到数据时更新状态
    // eslint-disable-next-line no-underscore-dangle
    if (data._isFirstChunk) {
      console.log('首次收到数据时更新状态');
      existingMsg.isThinkingLoading = false; // 关闭
      existingMsg.isLoading = false;
      existingMsg.id = data.message_id || existingMsg.id;
      existingMsg.isTemp = false;
    }
    console.log('[DEBUG]', {
      hasThink: !!thinkingContent,
      isFirst: data._isFirstChunk,
      currentLoadingState: existingMsg.isThinkingLoading,
    });
  } else {
    console.log('existingMsg === false');
    messages.push({
      message_id: data.message_id,
      conversation_id: data.conversation_id,
      type: 'assistant', // 助手信息 类型标识
      content: data.answer || '',
      isLoading: false,
      isTemp: !data.message_id,
      timestamp: Date.now(),
      isThinkingLoading: false,
      showThinking: false,
      thinkingContent: '',
    });
  }
  scrollToBottom();
};

// 流式数据内容解析方法
const extractThinkingContent = (rawText) => {
  // 捕获未闭合的起始标签
  const openMatch = rawText.match(/<think>([\s\S]*)/i);
  // console.log('捕获未闭合的起始标签', openMatch);
  if (openMatch) {
    return {
      thinkingContent: openMatch[1],
      cleanedContent: rawText.replace(openMatch[0], ''),
      hasOpenTag: true,
    };
  }

  // 捕获未闭合的结束标签（意外情况处理）
  const closeMatch = rawText.match(/([\s\S]*?)<\/think>/i);
  if (closeMatch) {
    return {
      thinkingContent: closeMatch[1],
      cleanedContent: rawText.replace(closeMatch[0], ''),
      hasOpenTag: false,
    };
  }

  // 无标签情况
  return {
    thinkingContent: '',
    cleanedContent: rawText,
    hasOpenTag: false,
  };
};

// 最终化消息
// eslint-disable-next-line camelcase
const finalizeMessage = (data: { message_id: any; _tempId: any; metadata: any; conversation_id: any }) => {
  console.log('metadata.usage', data.metadata.usage);
  if (data.metadata.retriever_resources && Array.isArray(data.metadata.retriever_resources)) {
    data.metadata.retriever_resources.forEach((resource, index) => {
      console.log(`------ 第 ${index + 1} 条引用信息 ------`);
      console.log('引用节段:', resource.segment_position || '无');
      console.log('引用文件名:', resource.document_name || '无');
      console.log('引用正文:', resource.content || '无');
      console.log('\n'); // 空行分隔
    });
  } else {
    console.error('retriever_resources 不是一个有效数组或未定义');
  }
  // messages.push(...data.metadata);
  // eslint-disable-next-line no-underscore-dangle
  const msg = messages.find((m) => m.message_id === data.message_id || m.id === data._tempId);
  if (msg) {
    msg.isCompleted = true;
    msg.metadata = data.metadata;
    msg.isLoading = false;
    msg.isTemp = false;

    // 当思考内容超过100字符时保持展开
    msg.showThinking = (msg.thinkingContent?.length || 0) > 100;

    // 确保ID一致性
    if (data.message_id) {
      msg.message_id = data.message_id;
      msg.id = data.message_id;
    }
  }

  // 清理可能的残留临时消息
  const tempIndex = messages.findIndex((m) => m.isTemp);
  if (tempIndex > -1) {
    messages.splice(tempIndex, 1);
  }

  // 清除 uploadFiles、inputs 参数
  uploadedFiles.value = [];
  inputs.value = {};

  currentConversationId.value = data.conversation_id; // 会话id
};

// 新增状态跟踪变量
const branchStatus = reactive({
  pendingBranches: 0, // 待完成分支数
  timeoutId: null, // 超时计时器
  lastActivity: Date.now(), // 最后活动时间戳
});

// 统一处理消息结束逻辑
const forceFinalize = (data) => {
  clearTimeout(branchStatus.timeoutId);
  finalizeMessage(data);
  console.warn('强制结束消息流程');
};

const handleUploadConfirm = (fileList) => {
  // 将新上传的文件合并到列表
  uploadedFiles.value = [...uploadedFiles.value, ...fileList];
};

const handleUpload = () => {
  uploadVisible.value = true;
};

const removeFile = (index) => {
  uploadedFiles.value.splice(index, 1);
};

// 处理推荐问题点击
const handleSuggestionClick = (question) => {
  yourMessage.value = question;
  sendMessage();
};

// 统一错误处理
const handleError = (errorData) => {
  isLoading.value = false;
  clearTimeout(branchStatus.timeoutId);
  const targetMessage = messages.findIndex((m) => m.id === errorData._tempId || m.message_id === errorData.message_id);

  console.log('targetMessage', targetMessage);
  if (targetMessage > -1) {
    // 保留原始消息结构，仅更新状态和内容
    Object.assign(messages[targetMessage], {
      content: formatErrorMessage(errorData),
      isLoading: false,
      isTemp: false, // 清除临时标记
      errorDetails: errorData,
    });
  } else {
    // 优化4：仅在无临时消息时创建新错误消息
    messages.push({
      id: `error_${Date.now()}`,
      type: 'assistant',
      content: formatErrorMessage(errorData),
      timestamp: Date.now(),
      isError: true,
      errorDetails: errorData,
    });
  }
  // 统一错误处理逻辑
  handleErrorNotification(errorData);
  scrollToBottom();
};

// 新增格式化方法
const formatErrorMessage = (errorData) => {
  const statusMap = {
    404: '对话不存在，请检查对话ID',
    500: '服务内部异常，请联系管理员',
  };

  const errorMap = {
    invalid_param: '请求参数异常，请检查输入内容',
    // ...其他错误码
  };

  return [statusMap[errorData.status], errorMap[errorData.code], errorData.message, '请求处理失败，请稍后重试'].find(
    Boolean,
  );
};

// 解耦错误提示逻辑
const handleErrorNotification = (errorData) => {
  const debugInfo = import.meta.env.DEV ? ` (${errorData.code || '无代码'} | ${errorData.status || '无状态'})` : '';

  MessagePlugin.error(`${formatErrorMessage(errorData)}${debugInfo}`);

  // 特殊错误处理
  if (errorData.code === 'provider_quota_exceeded') {
    console.error('触发额度告警逻辑');
    // 可以添加监控上报逻辑
  }
};

// 处理父容器滚动事件
const handleMainScroll = () => {
  const mainContainer = document.querySelector('.tdesign-starter-layout') as HTMLElement;
  if (!mainContainer) return;

  // 计算是否接近底部
  const isNearBottom =
    mainContainer.scrollTop + mainContainer.clientHeight >= mainContainer.scrollHeight - SCROLL_THRESHOLD;

  // 更新自动滚动状态
  autoScroll.value = isNearBottom;
};

// 辅助函数 处理父容器滚动事件
const scrollToBottom = () => {
  console.log('scrollToBottom');
  const mainContainer = document.querySelector('.tdesign-starter-layout') as HTMLElement;
  if (!mainContainer || !autoScroll.value) return;

  mainContainer.scrollTo({
    top: mainContainer.scrollHeight,
    behavior: 'smooth',
  });
};

const handleRouteEnter = () => {
  inputs.value = JSON.parse(route.query.inputs); // 解析回对象
  yourMessage.value = route.query.query;
  currentUser.value = route.query.user;
  console.log('handleRouteEnter', inputs.value);
  console.log('handleRouteEnter', yourMessage.value);
  console.log('handleRouteEnter', currentUser.value);
  sendMessage();
};

const loadHistoryData = async () => {
  const params = {
    conversation_id: route.params.id,
    user: user.userInfo.name,
  };
  const res = await fetchMessages(params);
  const processedData = processHistoryData(res);
  if (processedData) {
    // 直接从路由状态获取
    // 清空原有数据
    messages.splice(0, messages.length);
    // 直接 push 新数据
    messages.push(...processedData);
    currentConversationId.value = processedData[0].conversation_id;
  }
};

// 数据处理函数
const processHistoryData = (sessionData: any) => {
  const rawData = sessionData.data || [];
  return rawData.flatMap((item) => [
    // 用户消息
    {
      id: item.id, // id
      conversation_id: item.conversation_id || '', // 如果需要连续对话则传入
      type: 'user', // 类型判断
      content: item.query, // 内容
      timestamp: item.created_at * 1000, // 转换为毫秒
    },
    // 助手消息
    {
      id: item.id,
      type: 'assistant', // 对应模板中的 msg.type === 'assistant'
      content: item.answer,
      timestamp: item.created_at * 1000,
      showThinking: false,
      isLoading: false,
    },
  ]);
};

const fetchUserInfo = async () => {
  currentUser.value = user.userInfo?.name || 'CMCC';
};

// 生命周期管理
onMounted(() => {
  const mainContainer = document.querySelector('.tdesign-starter-layout');
  if (mainContainer) {
    mainContainer.addEventListener('scroll', handleMainScroll);
  }
});

onMounted(() => {
  fetchUserInfo();
});

onBeforeUnmount(() => {
  const mainContainer = document.querySelector('.tdesign-starter-layout');
  if (mainContainer) {
    mainContainer.removeEventListener('scroll', handleMainScroll);
  }
});

// 监听路由变化（包括首次进入）
watch(
  () => route.path,
  (newPath, oldPath) => {
    console.log('route', `${newPath}←${oldPath}`);
    console.log('route type', route.query.type);
    // type === 1 则为 创建新的会话
    if (route.query.type === '1') {
      handleRouteEnter();
    }
    if (route.query.type === '2') {
      loadHistoryData();
    }
  },
  { immediate: true }, // 立即触发以处理首次加载
);
</script>

<style lang="less" scoped>
@import url('./index.less');
.custom-back-bottom {
  transform: rotate(180deg); /* 翻转箭头方向 */
  //bottom: 80px; /* 调整默认位置 */
}
</style>
